package com.jhj.provider.bm.config;

import java.sql.SQLException;
import java.util.Arrays;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
@MapperScan(basePackages = BDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "busSqlSessionFactory")
@EnableConfigurationProperties(MybatisProperties.class)
public class BDataSourceConfig implements EnvironmentAware {

	@Autowired
	private MybatisProperties properties;

	private static final Logger LOGGER = LoggerFactory.getLogger(BDataSourceConfig.class);
	public static final String PACKAGE = "com.jhj.provider.bm.po.b.mapper";
	public static final String MAPPER_LOCAL = "classpath:mapper/b/*.xml";

	private Environment environment;
	private RelaxedPropertyResolver propertyResolver;

	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment;
		this.propertyResolver = new RelaxedPropertyResolver(environment, "spring.datasource.");
	}

	// 注册dataSource
	@Primary
	@Bean(initMethod = "init", destroyMethod = "close")
	public DruidDataSource busDataSource() {
		if (StringUtils.isBlank(propertyResolver.getProperty("url"))) {
			System.out.println("Your database connection pool configuration is incorrect!"
					+ " Please check your Spring profile, current profiles are:"
					+ Arrays.toString(environment.getActiveProfiles()));
			throw new ApplicationContextException("Database connection pool is not configured correctly");
		}
		DruidDataSource druidDataSource = new DruidDataSource();
		druidDataSource.setDriverClassName(propertyResolver.getProperty("driver-class-name"));
		druidDataSource.setUrl(propertyResolver.getProperty("url"));
		druidDataSource.setUsername(propertyResolver.getProperty("username"));
		druidDataSource.setPassword(propertyResolver.getProperty("password"));
		druidDataSource.setInitialSize(Integer.parseInt(propertyResolver.getProperty("initialSize")));
		druidDataSource.setMinIdle(Integer.parseInt(propertyResolver.getProperty("minIdle")));
		druidDataSource.setMaxActive(Integer.parseInt(propertyResolver.getProperty("maxActive")));
		druidDataSource.setMaxWait(Integer.parseInt(propertyResolver.getProperty("maxWait")));
		druidDataSource.setTimeBetweenEvictionRunsMillis(
				Long.parseLong(propertyResolver.getProperty("timeBetweenEvictionRunsMillis")));
		druidDataSource.setMinEvictableIdleTimeMillis(
				Long.parseLong(propertyResolver.getProperty("minEvictableIdleTimeMillis")));
		druidDataSource.setValidationQuery(propertyResolver.getProperty("validationQuery"));
		druidDataSource.setTestWhileIdle(Boolean.parseBoolean(propertyResolver.getProperty("testWhileIdle")));
		druidDataSource.setTestOnBorrow(Boolean.parseBoolean(propertyResolver.getProperty("testOnBorrow")));
		druidDataSource.setTestOnReturn(Boolean.parseBoolean(propertyResolver.getProperty("testOnReturn")));
		druidDataSource.setPoolPreparedStatements(
				Boolean.parseBoolean(propertyResolver.getProperty("poolPreparedStatements")));
		druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(
				Integer.parseInt(propertyResolver.getProperty("maxPoolPreparedStatementPerConnectionSize")));
		try {
			druidDataSource.setFilters(propertyResolver.getProperty("filters"));
		} catch (SQLException e) {
			LOGGER.error("create business datasource failed, error : {}", e.getMessage());
			throw new RuntimeException(e);
		}
		return druidDataSource;
	}

	@Bean(name = "busSqlSessionFactory")
	@Primary
	public SqlSessionFactory sqlSessionFactory() {
		final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
		sessionFactoryBean.setDataSource(busDataSource());
		// set configuration by hand,it will config before 通用mapper's autoconfiguration
		sessionFactoryBean.setConfiguration(properties.getConfiguration());
		try {
			sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCAL));
			return sessionFactoryBean.getObject();
		} catch (Exception e) {
			LOGGER.error("config business SqlSessionFactory failed，error:{}", e.getMessage());
			throw new RuntimeException(e);
		}
	}

	@Primary
	@Bean(name = "busTransactionManager")
	public DataSourceTransactionManager transactionManager() {
		return new DataSourceTransactionManager(busDataSource());
	}

}